package com.xhs.interceptor;

import cn.dev33.satoken.sign.SaSignUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpMethod;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @desc: 签名校验的拦截器
 * @projectName: java-tools-parent
 * @author: xhs
 * @date: 2023-8-27 027 17:56
 * @version: JDK 1.8
 */
@Slf4j
public class SignInterceptor implements HandlerInterceptor {

    /**
     * 创建一个签名校验的拦截器
     */
    public SignInterceptor() {

    }

    /**
     * 每次请求之前触发的方法
     *
     * @param request  request
     * @param response response
     * @param handler  handler
     * @return boolean
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果是OPTIONS请求，让其响应一个 200状态码，说明可以正常访问
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            // 放行OPTIONS请求
            return true;
        }
        // 保存传递过来的参数
        Map<String, String> map = new HashMap<>(16);

        // 在拦截器中获取处理方法的参数，并检查是否带有 @RequestBody 注解
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
        for (MethodParameter parameter : methodParameters) {
            if (parameter.hasParameterAnnotation(RequestBody.class)) {
                // 参数带有 @RequestBody 注解
                // 获取请求体参数
                RequestWrapper requestWrapper = new RequestWrapper(request);
                String requestBody = requestWrapper.getBody();
                if (StringUtils.hasLength(requestBody)) {
                    JSONObject jsonObject = JSONObject.parseObject(requestBody);
                    map = JSON.parseObject(jsonObject.toJSONString(), HashMap.class);
                    log.info("请求体参数map:{}", map);
                }
            } else {
                // 参数不带 @RequestBody 注解
                // 非请求体参数
                Enumeration<String> parameterNames = request.getParameterNames();
                // 遍历参数名，并获取对应的参数值
                while (parameterNames.hasMoreElements()) {
                    String paramName = parameterNames.nextElement();
                    String paramValue = request.getParameter(paramName);
                    // 处理动态参数，如打印参数名和参数值
                    map.put(paramName, paramValue);
                }
                log.info("非请求体参数map:{}", map);
            }
        }
        // 1、校验请求中的签名
        SaSignUtil.checkParamMap(map);
        return true;
    }
}
